﻿#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEditor;

namespace BF
{

    public static class PlayerDataInfoTools
    {

        [MenuItem("BF/PlayerData/Creat PlayerData.cs")]
        public static void CreatPlayerData()
        {
            Assembly Assembly_CSharp = Assembly.Load("Assembly-CSharp");
            IEnumerable<Type> playerDateTypes = Assembly_CSharp.GetTypes().Where(it => it.IsClass && it.IsSubclassOf(typeof(PlayerDataInfo)));
            CreatPlayerData(playerDateTypes);

            AssetDatabase.Refresh();
        }

        private static void CreatPlayerData(IEnumerable<Type> types)
        {
            string path = Application.dataPath + "/__BF/Scripts/PlayerData/PlayerData.cs";
            
            StringBuilder builder = new StringBuilder();
            builder.AppendLine("using BF;");
            builder.AppendLine("using System;");
            builder.AppendLine("using System.Linq;");
            builder.AppendLine("using System.Collections;");
            builder.AppendLine("using System.Collections.Generic;");
            builder.AppendLine("using System.Reflection;");
            builder.AppendLine("using UnityEngine;");
            HashSet<string> nameSpaces = new HashSet<string>(types.Where(it => !string.IsNullOrEmpty(it.Namespace)).Select(it => it.Namespace));
            foreach (string @namespace in nameSpaces)
            {
                builder.AppendLine($"using {@namespace};");
            }
            builder.AppendLine("");
            builder.AppendLine("/// <summary>");
            builder.AppendLine("/// 用户数据：使用BF/PlayerData/Creat PlayerData.cs自动生成");
            builder.AppendLine("/// </summary>");
            builder.AppendLine("public static class PlayerData");
            builder.AppendLine("{");
            foreach (Type type in types)
            {
                builder.AppendLine("");
                builder.AppendLine($"    public static {type.Name} {FirstCharToLower(type.Name)} {{ get; private set; }} = PlayerDataInfo.Load<{type.Name}>();");
            }
            builder.AppendLine("");
            builder.AppendLine($"    private static readonly PlayerDataInfo[] allInfos = new PlayerDataInfo[] {{");
            foreach (Type type in types)
            {
                builder.AppendLine($"        {FirstCharToLower(type.Name)},");
            }
            builder.AppendLine("    };");


            builder.AppendLine(@"
    static PlayerData()
    {
        if (!Application.isPlaying)
        {
            return;
        }

        Timer.Pop().Delay(5).Loop(-1, 60).Action(AutoSave).Execute();

        UnityMonoEvent.onApplicationPause += (isPause) => SaveAll();
        UnityMonoEvent.onApplicationFocus += (isFocus) => SaveAll();
        UnityMonoEvent.onApplicationQuit += () => SaveAll();
    }

    public static void Clear<T>() where T : PlayerDataInfo, new()
    {
        T newInfo = PlayerDataInfo.New<T>();

        string propertyName = typeof(T).Name;
        propertyName = char.ToLower(propertyName[0]) + propertyName.Substring(1);
        PropertyInfo property = typeof(PlayerData).GetProperty(propertyName);
        property.SetValue(typeof(PlayerData), newInfo);

        for (int i = 0; i < allInfos.Length; ++i)
        {
            if (allInfos[i].GetType().Equals(typeof(T)))
            {
                allInfos[i] = newInfo;
                break;
            }
        }
    }

    private static void AutoSave()
    {
        foreach(PlayerDataInfo info in allInfos)
        {
            if (info.isAutoSave)
            {
                info.Save();
            }
        }
        PlayerPrefs.Save();
    }

    public static void SaveAll()
    {
        foreach (PlayerDataInfo info in allInfos)
        {
            info.Save();
        }
        PlayerPrefs.Save();
    }
}
");
            string dir = Path.GetDirectoryName(path);
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            File.WriteAllText(path, builder.ToString());

            Debug.Log("PlayerData.cs 代码生成完毕");
        }

        private static string FirstCharToLower(string str)
        {
            char[] chars = str.ToArray();
            chars[0] = Char.ToLower(chars[0]);
            return new string(chars);
        }
    }
}


#endif